{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Working with local coordinates \n",
    "\n",
    "<img align=\"right\" src=\"https://anitagraser.github.io/movingpandas/assets/img/movingpandas.png\">\n",
    "\n",
    "[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/anitagraser/movingpandas/master?filepath=tutorials/5-local-coordinates.ipynb)\n",
    "\n",
    "**<p style=\"color:#e31883\">This notebook demonstrates the current development version of MovingPandas.</p>**\n",
    "\n",
    "For tutorials using the latest release visit https://github.com/anitagraser/movingpandas-examples.\n",
    "\n",
    "\n",
    "\n",
    "This tutorial uses data extracted from video footage of a soccer game that was published in https://github.com/Friends-of-Tracking-Data-FoTD/Last-Row\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import urllib\n",
    "import os\n",
    "import pandas as pd\n",
    "import geopandas as gpd\n",
    "from geopandas import GeoDataFrame, read_file\n",
    "from shapely.geometry import Point, LineString, Polygon\n",
    "from fiona.crs import from_epsg\n",
    "from datetime import datetime, timedelta\n",
    "from matplotlib import pyplot as plt\n",
    "import holoviews as hv\n",
    "\n",
    "import sys\n",
    "sys.path.append(\"..\")\n",
    "import movingpandas as mpd\n",
    "mpd.show_versions()\n",
    "\n",
    "import warnings\n",
    "warnings.simplefilter(\"ignore\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from os.path import exists\n",
    "from urllib.request import urlretrieve\n",
    "\n",
    "def get_df_from_gh_url(url):\n",
    "    file = f'soccer.csv'\n",
    "    if not exists(file):\n",
    "        urlretrieve(url, file)\n",
    "    return pd.read_csv(file)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "input_file = \"https://raw.githubusercontent.com/anitagraser/Last-Row/master/datasets/positional_data/liverpool_2019.csv\"\n",
    "df = get_df_from_gh_url(input_file)\n",
    "df.drop(columns=['Unnamed: 0'], inplace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plays = list(df.play.unique())\n",
    "\n",
    "def to_timestamp(row):\n",
    "    # plays to date\n",
    "    day = plays.index(row.play)+1\n",
    "    start_time = datetime(2019,1,day,12,0,0)\n",
    "    # frames to time\n",
    "    td = timedelta(milliseconds=1000/20*row.frame)\n",
    "    return start_time + td\n",
    "\n",
    "# frame: the frame number for the current location. Data provided has 20 frames per second\n",
    "df['time'] = df.apply(to_timestamp, axis=1)\n",
    "df.set_index('time', inplace=True)\n",
    "\n",
    "# the preferred size for many professional teams' stadiums is 105 by 68 metres, accoring to https://en.wikipedia.org/wiki/Football_pitch\n",
    "pitch_length = 105\n",
    "pitch_width = 68\n",
    "df.x = df.x / 100 * pitch_length \n",
    "df.y = df.y / 100 * pitch_width\n",
    "\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "CRS = None\n",
    "traj_collection = mpd.TrajectoryCollection(df, 'player', x='x', y='y', crs=CRS)\n",
    "mpd.TemporalSplitter(traj_collection).split(mode=\"day\")\n",
    "print(f\"Finished creating {len(traj_collection)} trajectories\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pitch = Polygon([(0, 0), (0, pitch_width), (pitch_length, pitch_width), (pitch_length, 0), (0, 0)])\n",
    "plotted_pitch = GeoDataFrame(pd.DataFrame([{'geometry': pitch, 'id': 1}]), crs=CRS).hvplot(color='white', alpha=0.5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "PLAY = 2\n",
    "title = f'Play {PLAY} {plays[PLAY]}'\n",
    "play_trajs = traj_collection.filter('play', plays[PLAY])\n",
    "play_trajs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "play_trajs.plot(column='team', colormap={'attack':'hotpink', 'defense':'turquoise'})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "type(play_trajs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "generalized = mpd.MinTimeDeltaGeneralizer(play_trajs).generalize(tolerance=timedelta(seconds=0.5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "hvplot_defaults = {'line_width':5, 'frame_height':350, 'frame_width':700, 'colorbar':True, 'tiles':None, 'geo':False,}\n",
    "generalized.hvplot(title=title,  c='speed', hover_cols=['player'], **hvplot_defaults)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "(\n",
    "    plotted_pitch * \n",
    "    generalized.hvplot(title=title,  c='speed', hover_cols=['player'], cmap='Viridis', **hvplot_defaults)\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pitch_img = hv.RGB.load_image(f'./data/soccer_field.png', bounds=(0,0,pitch_length,pitch_width)) \n",
    "(\n",
    "    pitch_img * \n",
    "    generalized.hvplot(title=title, c='team', colormap={'attack':'limegreen', 'defense':'purple'}, \n",
    "                    hover_cols=['player'],**hvplot_defaults) * \n",
    "    generalized.get_start_locations().hvplot(label='start', color='orange')\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Continue exploring MovingPandas\n",
    "\n",
    "1. [Getting started](1-getting-started.ipynb)\n",
    "1. [Handling trajectory data files (reading & writing)](2-reading-data-from-files.ipynb)\n",
    "1. [TrajectoryCollection aggregation (flow maps)](3-generalization-and-aggregation.ipynb)\n",
    "1. [Stop detection](4-stop-detection.ipynb)\n",
    "1. [Working with local coordinates](5-local-coordinates.ipynb)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
